

import numpy as np 
import math 
import sys 

t_input = [2,3,7,9,10,11,12,13,18,19,22,23,26,27,30,31]
ti_input = len(f'{np.max(t):b}')

# 判断两个数是否只有一个二进制不一样
def nor(x1, x2):
    return x1^x2

# 判断两个集合是否相邻, 只有一位不同
def is_track(x1, x2):
    ts = [nor(x1[i],x2[i]) for i in range(len(x1))]
    k = 0 
    for t in ts: k |= t  
    if k == 0: return False
    k = math.log2(k)  
    return  k == int(k) # 

# 将所有数据进行分组和比对
def sfun(xs, ts):
    xs_t = []
    if len(xs) == 0: return 
    xs_i = [] # 记录已经添加过的结构
    for i in range(len(xs)-1):
        etr = False
        for j in range(i+1, len(xs)):
            if is_track(xs[i],xs[j]):
                xs_t.append(xs[i]+xs[j])
                xs_i += [i, j]
                etr = True
        # 将不能合并的数据丢在完成缓冲区
        xs_it = set(xs_i)
        # 使用 集合 过滤重复
        exs = set(xs[i])
        if not etr and i not in xs_it and exs not in ts: ts.append(exs)
    # 递归
    sfun(xs_t, ts)

# 数据处理一下 
t_input.sort() # 做一个排序
xs = [[x] for x in t_input]  # 将元素变成列表供下面sfun递归参数统一
ts = [] # 保存分组好的数据
sfun(xs, ts)

### 过滤重复
# 1. 根据分组建立数字和组的对应关系
kt = {}
for i,t in enumerate(ts):
    for s in t:
        if s not in kt: kt[s] = []
        kt[s].append(i)


# 2. 先将必选组拿出来, 数字只在该组出现过.
mteam = []
for n in kt:
    if len(kt[n]) == 1 and kt[n][0] not in mteam: 
        mteam.append(kt[n][0])

# 3. 确定已覆盖有的数字
over_n = []
for m in mteam:
    for n in ts[m]:
        if n not in over_n: over_n.append(n)


# 4. 找到没有覆盖的数字和它在分组的关系
no_over_t = []
for n in kt:
    if n  in over_n: continue 
    no_over_t.append(kt[n])

# 5. 剩余的部分, 分组没有被选,那就排列组合一下
# ps: 我这里没有足够的时间测试和样例研究, 所以就直接排列组合一下
import itertools
tp = itertools.product(*no_over_t)
est_all = [list(t)+mteam for t in tp] # 得到所有分组

# 结果打印
team_syms = []
for i, t in enumerate(est_all):
    team_sym = []
    for e in t:
        # 找到被切换的
        ts_e = list(ts[e])
        t = ts_e[0]
        tn = 0
        for n in ts_e[1:]:
            tn |= t ^ n       
        item_sym = ''  
        for b in range(ti_input-1,-1,-1):
            if (1<<b & tn) != 0: continue
            t_sym = chr(ord('A')+ti_input-b-1)
            if (1<<b & t) != 0: item_sym+=f'{t_sym}'
            else: item_sym+=f'\overline{{{t_sym}}}'
        team_sym.append(item_sym)
    team_syms.append(team_sym)

for i, t in enumerate(team_syms):
    print(f'分组{i+1} : ${" + ".join(t)}$')